package com.maimao.user.controller;

import cn.hutool.core.util.StrUtil;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.maimao.core.constant.RedisKeys;
import com.maimao.core.model.auth.AuthUser;
import com.maimao.core.model.resp.Result;
import com.maimao.core.utils.RegexUtils;
import com.maimao.email.EmailSender;
import com.maimao.model.user.User;
import com.maimao.model.user.input.CodeVerifyInput;
import com.maimao.model.user.input.EmailInput;
import com.maimao.user.controller.base.BaseController;
import com.maimao.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.maimao.core.constant.Constants.EMPTY;
import static com.maimao.core.constant.Constants.ONE;

/**
 * @author MaoLin Wang
 * @date 2020/12/14 1:28 下午
 */
@Slf4j
@RestController
@RequestMapping("/web/code")
public class CodeController extends BaseController {
    public static final String EMAIL_BIND_CONTENT = "您正在进行绑定邮箱操作，此次验证码为：<span style='color:red;font-weight:600;font-size:18px'>{}</span><br/>(如果此邮件不是您发起的，请忽略...)";
    public static final String EMAIL_VERIFY_CONTENT = "您正在进行邮件认证，此次验证码为：<span style='color:red;font-weight:600;font-size:18px'>{}</span><br/>(如果此邮件不是您发起的，请忽略...)";
    @Autowired
    private DefaultKaptcha defaultKaptcha;
    @Autowired
    private RedisTemplate redisTemplate;
    private static final Integer duration = 60;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private EmailSender emailSender;

    @Resource(name = "userEmailSendPool")
    private ThreadPoolTaskExecutor userEmailSendPool;

    /**
     * 绑定邮箱主题
     */
    @Value("${maimao.mail.bindEmail.subject}")
    private String bindEmailSubject;

    /**
     * 邮件验证码认证主题
     */
    @Value("${maimao.mail.verify.subject}")
    private String emailVerifySubject;

    /**
     * 使用用户自己的手机发送手机验证码 TODO 整合阿里大于
     */
    @PostMapping("/mobile-code")
    public Result<?> mobileCode(@RequestBody Map<String, String> data, @RequestParam(value = "defaultMobile", required = false, defaultValue = "0") Integer defaultMobile) {
        String mobile = data.get("mobile");
        if (defaultMobile.equals(ONE)) {
            //使用用户默认手机号
            AuthUser authUser = checkAndGetAuthUser();
            User user = userMapper.selectById(authUser.getId2Long());
            if (null == user || StrUtil.isEmpty(user.getMobile())) {
                return Result.notValid("尚未绑定手机");
            }
            mobile = user.getMobile();
        }
        if (StringUtils.isEmpty(mobile)) {
            return Result.notValid("请填写手机号");
        }
        if (!RegexUtils.checkPhone(mobile)) {
            return Result.notValid("手机号格式非法");
        }
        String code = defaultKaptcha.createText();
        redisTemplate.opsForValue().set(RedisKeys.SECURITY_OPERATION_MOBILE_CODE + mobile, code, duration, TimeUnit.SECONDS);
        log.info("生成手机验证码:{} => {}", mobile, code);
        return Result.ok();
    }

    /**
     * 绑定邮箱发送邮箱验证码
     */
    @PostMapping("/bindEmailCode")
    public Result<?> bindEmailSendCode(@RequestBody EmailInput input) {
        if (input == null || StrUtil.isEmpty(input.getEmail())) {
            return Result.notValid("请填写邮箱地址");
        }
        if (!RegexUtils.checkEmail(input.getEmail())) {
            return Result.notValid("邮箱地址格式非法");
        }
        User user = userMapper.selectByEmail(input.getEmail());
        if (null != user) {
            return Result.notValid("此邮箱已被绑定");
        }
        userEmailSendPool.submit(() -> {
            String code = defaultKaptcha.createText();
            redisTemplate.opsForValue().set(RedisKeys.SECURITY_OPERATION_EMAIL_CODE + input.getEmail(), code, duration, TimeUnit.SECONDS);
            log.info("准备发送邮件..........");
            String content = StrUtil.format(EMAIL_BIND_CONTENT, code);

            log.info("绑定邮箱——发送邮件，内容：{},to:{},code:{}", content, input.getEmail(), code);
            emailSender.sendHtml(bindEmailSubject, input.getEmail(), content);

        });
        return Result.ok("发送成功，请注意查收！");
    }

    /**
     * 通用邮件验证[使用用户默认邮件]
     */
    @PostMapping("/emailCode")
    public Result<?> emailCode(@RequestBody EmailInput input) {
        String email = EMPTY;
        if (input.isDefaultEmail()) {
            AuthUser authUser = checkAndGetAuthUser();
            User user = userMapper.selectById(authUser.getId2Long());
            if (user == null || StrUtil.isEmpty(user.getEmail())) {
                return Result.notValid("尚未绑定邮箱");
            }
            email = user.getEmail();
        } else if (input == null || StrUtil.isEmpty((email = input.getEmail()))) {
            return Result.notValid("请输入邮箱地址");
        }

        if (!RegexUtils.checkEmail(email)) {
            return Result.notValid("邮箱地址格式非法");
        }
        String finalEmail = email;
        userEmailSendPool.submit(() -> {
            String code = defaultKaptcha.createText();
            redisTemplate.opsForValue().set(RedisKeys.SECURITY_OPERATION_EMAIL_CODE + finalEmail, code, duration, TimeUnit.SECONDS);
            log.info("准备发送邮件..........");
            String content = StrUtil.format(EMAIL_VERIFY_CONTENT, code);

            log.info("邮箱验证码认证——发送邮件，内容：{},to:{},code:{}", content, finalEmail, code);
            emailSender.sendHtml(emailVerifySubject, finalEmail, content);

        });
        return Result.ok("发送成功，请注意查收！");
    }


    /**
     * 校验手机验证
     */
    @PostMapping("/verifyMobileEmailCode")
    public Result<?> verifyMobileCode(@RequestBody @Validated CodeVerifyInput input) {

        AuthUser authUser = checkAndGetAuthUser();
        User user = userMapper.selectById(authUser.getId2Long());
        if (user == null) {
            return Result.notValid("非法用户");
        }
        String key;
        if (input.isMobile()) {
            key = RedisKeys.SECURITY_OPERATION_MOBILE_CODE + user.getMobile();
        } else {
            key = RedisKeys.SECURITY_OPERATION_EMAIL_CODE + user.getEmail();
        }
        Object cacheCode = redisTemplate.opsForValue().get(key);
        if (null == cacheCode) {
            return Result.notValid("验证码已过期");
        }
        if (!cacheCode.equals(input.getCode())) {
            return Result.notValid("验证码错误");
        }
        redisTemplate.opsForValue().set(RedisKeys.VALIDATED + authUser.getId(), 1, 60, TimeUnit.SECONDS);
        return Result.okData(true);
    }


}
